package system;

import datacontrol.DAO;
import util.Toolkit;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet waar de vragen worden afgehandeld.
 * Als er een antwoord wordt meegegeven wordt deze direct opgeslagen in de db.
 * 
 * @author Jeroen
 */
public class BeantwoordVraag extends HttpServlet {

    /** 
     * Handelt het eventuele antwoord af en laat de vraag zien. 
     * Zodra een vraag gevonden is stuurt de servlet deze door naar vraag.jsp
     * aan de gebruiker.
     * 
     * @param request en response
     * @throws ServletException, IOException
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (!Toolkit.checkLogin(request)) {
            // Ogenschijnlijk is de gebruiker niet ingelogd
            response.sendRedirect("EnqueteOphaler");
            return;
        }
        
        try {
            if (Integer.parseInt(request.getAttribute("alBegonnen").toString()) > 0) {
                // Als gebruiker in een onvoltooide enquete moet de antwoorden wel weer ingevuld worden
                zetAntwoordenInSessie(request, Integer.parseInt(request.getSession().getAttribute("userId").toString()),
                        Integer.parseInt(request.getSession().getAttribute("enqueteId").toString()));
            }
        } catch (NullPointerException e) {
            // Wordt gegooid als je niet direct van 'EnqueteStarter' komt. Geen probleem!
        }

        String[] vragen;
        int vragenCounter;
        int vorigeCounter = 0;
        try {
            // Onderstaand is voor het opslaan van de antwoorden in de sessie, hiervoor is namelijk de 'oude' counter
            // nodig. De huidige counter wordt iets verder onder meteen veranderd. (Het is even niet anders).
            vorigeCounter = Integer.parseInt(request.getSession().getAttribute("vragenCounter").toString());
            // Ga naar volgende of vorige vraag!
            if (request.getParameter("nav_knop").toString().equals("Volgende vraag")) {
                request.getSession().setAttribute("vragenCounter", Integer.parseInt(request.getSession().getAttribute("vragenCounter").toString()) + 1);
            } else if (request.getParameter("nav_knop").toString().equals("Vorige vraag")) {
                request.getSession().setAttribute("vragenCounter", Integer.parseInt(request.getSession().getAttribute("vragenCounter").toString()) - 1);
            }
        } catch (NullPointerException e) {
            // Gebruiker komt ogenschijnlijk 'voor het eerst aan' (knoppen vooruit of achteruit niet gevonden)
            // Maakt niets uit!
        }
        // Eerst checken of gebruiker van een andere vraag komt (Zoja, verwerk de antwoorden eerst)
        try {
            vragen = (String[]) request.getSession().getAttribute("vragen");
            vragenCounter = Integer.parseInt(request.getSession().getAttribute("vragenCounter").toString());
        } catch (NullPointerException e) {
            // Als vragen en of vragenCounter niet geset is, mag de gebruiker hier helemaal niet zijn.
            // Stuur terug naar de hoofdpagina.
            Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE,
                    "Vragen en vragencounter niet geset. Stuur gebruiker terug naar hoofdpagina", e);
            response.sendRedirect("EnqueteOphaler");
            return;
        }
        try {
            // Haal antwoord op van de vraag
            String antwoord = request.getParameter("antwoord").toString();
            HashMap<String, String> antwoorden = (HashMap<String, String>) request.getSession().getAttribute("antwoorden");
            if (antwoord.equals("")) {
                throw new NullPointerException();
            }
            // Zo te zien is er een antwoord ingevuld, sla deze op in de sessie (voor als gebruiker terug navigeert)
            // en ook in de database, voor als de gebruiker stopt met het maken van de enquete
            antwoorden.put(String.valueOf(vorigeCounter), antwoord);
            request.getSession().setAttribute("antwoorden", antwoorden);
            int userId = Integer.parseInt(request.getSession().getAttribute("userId").toString());
            int vraagId = Integer.parseInt(vragen[vorigeCounter].toString());
            try {
                ArrayList<HashMap<String, String>> result = DAO.selectQuery("SELECT `antwoord` "
                        + "FROM `Antwoord` "
                        + "WHERE `Gebruiker_idGebruiker` = " + userId
                        + " AND `Vraag_idVraag` = " + vraagId);
                // Haal eventuele toelichting op en stop in sessie voor later gebruik
                String toelichting = request.getParameter("extra").toString();
                HashMap<String, String> extra = (HashMap<String, String>) request.getSession().getAttribute("extra");
                if (toelichting.equals("")) {
                    toelichting = "";
                }
                extra.put(String.valueOf(String.valueOf(vorigeCounter)), toelichting);
                request.getSession().setAttribute("extra", extra);
                if (result.size() == 1 && !result.get(0).get("antwoord").equals("")) {
                    // In dit geval is er al eerder een antwoord gegeven. 
                    // Voer in dit geval een Update query uit
                    DAO.executeUpdate("UPDATE `Antwoord` "
                            + "SET `antwoord` = '" + antwoord.replace("'", "''") + "', `toelichting` = '" + toelichting + "'"
                            + "WHERE `Gebruiker_idGebruiker` = " + userId
                            + " AND `Vraag_idVraag` = " + vraagId);
                } else {
                    // Niet dus, voer Insert query uit
                    DAO.executeUpdate("INSERT INTO `Antwoord` VALUES('" + userId + "', '" + vraagId + "', '" + antwoord + "', '" + toelichting + "' )");
                }
                // Antwoord zou opgeslagen moeten zijn...
            } catch (SQLException ex) {
                // TODO Afhandling Exception
            }
        } catch (NullPointerException e) {
            // TODO Afhandeling Exception
            Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE, "Geen antwoord gegeven.");
        }
        // Einde afhandeling antwoorden e.d....
        // ---------------------------------------------------------------
        // ---------------------------------------------------------------
        // Probeer nu vragen op te halen om de juiste vraag te laten zien.

        try {
            if (vragenCounter == 0) {
                request.setAttribute("eerstevraag", true);
            } else if (vragenCounter == vragen.length - 1) {
                request.setAttribute("laatstevraag", true);
            }

            try {
                // Klaar om vraag te tonen. Haal eerst vraag op uit db
                ArrayList<HashMap<String, String>> vraag = DAO.selectQuery("SELECT `type`, `vraagstelling`, `rowid` "
                        + "FROM `Vraag` "
                        + "WHERE `Vraag`.`rowid` = " + vragen[vragenCounter]);
                HashMap<String, String> antwoorden = (HashMap<String, String>) request.getSession().getAttribute("antwoorden");
                // Dit stukje is voor het voltooien van de enquete, als de gebruiker alles heeft ingevuld
                try {
                    if (request.getParameter("nav_knop").toString().equals("Verzend antwoorden")) {
                        // Gebruiker is bij eind van de enquete, check of alle antwoorden zijn beantwoord.
                        // Zoja, stop de boel in de database. Zo nee, geef foutmelding.
                        for (String key : antwoorden.keySet()) {
                            if (antwoorden.get(key).equals("")) {
                                request.setAttribute("error_enquete",
                                        "Niet alle antwoorden zijn ingevuld, vult u deze alstublieft in voordat u de antwoorden verzendt.");
                                throw new NullPointerException();
                            }
                        }
                        if (antwoorden.size() != vragen.length) {
                            request.setAttribute("error_enquete",
                                    "Niet alle antwoorden zijn ingevuld, vult u deze alstublieft in voordat u de antwoorden verzendt.");
                            throw new NullPointerException();
                        }
                        // Ogenschijnlijk is alles ingevuld: voer maar in, in de database.
                        voltooiEnquete(Integer.parseInt(request.getSession().getAttribute("userId").toString()),
                                Integer.parseInt(request.getSession().getAttribute("enqueteId").toString()));
                        response.sendRedirect("EnqueteOphaler");
                        return;
                    }
                } catch (NullPointerException e) {
                    // TODO Afhandeling
                }

                // Check of vraag meerkeuze is. Zoja: haal de bijbehorende antwoorden op
                if (vraag.get(0).get("type").equals("Meerkeuze")) {
                    ArrayList<HashMap<String, String>> res = DAO.selectQuery("SELECT `Antwoord` "
                            + "FROM `VraagInAntwoord` "
                            + "WHERE `VraagId` = " + vraag.get(0).get("rowid"));
                    ArrayList<String> antwoordenInVraag = new ArrayList<String>();
                    for (HashMap<String, String> s : res) {
                        antwoordenInVraag.add(s.get("Antwoord"));
                    }
                    request.setAttribute("mc_antwoorden", antwoordenInVraag);
                }

                request.setAttribute("result", vraag);
                request.setAttribute("vragenCounter", vragen[vragenCounter]);
                getServletContext().getRequestDispatcher("/vraag.jsp").forward(request, response);
            } catch (SQLException e) {
                Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE,
                        "Iets misgegaan met opgehalen van enquetevragen.", e);
                response.sendRedirect("EnqueteOphaler");
                return;
            } catch (ArrayIndexOutOfBoundsException e) {
                Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE,
                        "Iets misgegaan met opgehalen van enquetevragen.", e);
                response.sendRedirect("EnqueteOphaler");
                return;
            }
        } catch (NullPointerException e2) { // Ook geen vragen en vragenCounter. Gebruiker terug naar index
            Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE, "Niks geset voor vragen beantwoorden.", e2);
            response.sendRedirect("EnqueteOphaler");
            return;
        }
    }

    private void voltooiEnquete(int gebruikerId, int enqueteId) {
        try {
            // Aangezien alle antwoorden (en toelichtingen) al zijn opgeslagen, zorg dat de db
            // 'weet' dat de enquete is voltooid.
            DAO.executeUpdate("UPDATE `EnqueteVanGebruiker` SET `voltooid` = 1 "
                    + "WHERE `Gebruiker_idGebruiker` = " + gebruikerId
                    + " AND `Enquete_idEnquete` = " + enqueteId);
            int iVoltooid = Integer.parseInt(DAO.selectQuery("SELECT `voltooid` "
                    + "FROM `Enquete` "
                    + "WHERE `rowid` = " + enqueteId).get(0).get("voltooid")) + 1;
            DAO.executeUpdate("UPDATE `Enquete` SET `voltooid` = " + iVoltooid + " WHERE `rowid` = " + enqueteId);
        } catch (SQLException ex) {
            Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE, "Voltooiing enquete mislukt.", ex);
        }
    }

    /*
     * Als een gebruiker eerder al antwoorden in heeft gevuld maar de enquete ergens heeft gestopt,
     * moeten de antwoorden wel weer in de sessie worden gezet zodat de gebruiker meteen doorkan.
     */
    private void zetAntwoordenInSessie(HttpServletRequest request, int gebruikerId, int enqueteId) {
        HashMap<String, String> antwoorden = new HashMap<String, String>();
        HashMap<String, String> toelichtingen = new HashMap<String, String>();
        try {
            ArrayList<HashMap<String, String>> result = DAO.selectQuery("SELECT `Antwoord`.`Vraag_idVraag`, `antwoord`, `toelichting`, `VraagNummer` "
                    + "FROM `Antwoord`, `VraagInEnquete` "
                    + "WHERE `VraagInEnquete`.`Vraag_idVraag` = `Antwoord`.`Vraag_idVraag` "
                    + " AND `Antwoord`.`Gebruiker_idGebruiker` = " + gebruikerId
                    + " AND `VraagInEnquete`.`Enquete_idEnquete` = " + enqueteId);
            if (!result.isEmpty()) {
                for (int i = 0; i < result.size(); i++) {
                    antwoorden.put(result.get(i).get("VraagNummer"), result.get(i).get("antwoord"));
                    if (!result.get(i).get("toelichting").equals("NULL")) {
                        toelichtingen.put(result.get(i).get("VraagNummer"), result.get(i).get("toelichting"));
                    }
                }
                request.getSession().setAttribute("antwoorden", antwoorden);
                request.getSession().setAttribute("extra", toelichtingen);
            }
        } catch (SQLException ex) {
            Logger.getLogger(BeantwoordVraag.class.getName()).log(Level.SEVERE, "Antwoorden ophaal query mislukt!", ex);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}